\documentclass[a4paper]{article}				%A4纸，article类型

\usepackage{xeCJK}							%中文环境
\usepackage{geometry}						%页面边距
\usepackage{indentfirst}						%首行缩进
\usepackage{listings}						%代码插入
\usepackage{graphicx}						%图片插入

\setlength{\parindent}{2em}					%缩进字符
\setCJKmainfont{SimSun}						%字体
\geometry{left=2.5cm,right=2cm,top=2.5cm,bottom=2.5cm}
											%页面边距

\renewcommand{\contentsname}{目录}
\renewcommand{\listfigurename}{插图目录}
\renewcommand{\listtablename}{表格目录}
\renewcommand{\refname}{参考文献}
\renewcommand{\abstractname}{摘要}
\renewcommand{\indexname}{索引}
\renewcommand{\tablename}{表}
\renewcommand{\figurename}{图}

\author{王政}
\title{商户管理平台开发文档}
\date{2014.01}

\begin{document}
\maketitle
%\begin{abstract}
%
%	\paragraph{关键字}
%
%\end{abstract}
\tableofcontents

\section{项目背景}
注意：项目根路径即应用跟路径，为platform文件夹。
\subsection{用户需求}
\paragraph{主需求}
本项目是从属与一个电子商务平台的功能模块，目的是为了满足电子商务平台商户对于商品的一系列管理需求。这些需求包括对商品的：增、改、删、查。
\paragraph{从需求}
本项目的实施，特别是数据库的实施模式将会极大的影响电子商务平台的其他功能模块的实现。
\subsection{技术需求}
由于用户需求的特殊情况，需要本项目代码具有较低的耦合性。
\subsection{部署环境}
Struts2+Hibernate4+tomcat7+Java7+GNU/Linux Ubuntu 12.04LTS Server
\section{开发规划与现状}
数据持久化层功能已经完成。应用服务器层、表现层三层已经完成了绝大多数功能\footnote{具体情况参考模块介绍}。
\subsection{数据持久化层}
建立platform库，使用Hibernate4框架进行操作。分为表：
\paragraph{order}
运单。指收货人为同一个人的不同商品的集合，往往在同一个运货单中发出。
\paragraph{order\_good}
订单。运单中商品描述，包括商品本身的描述以及其运单标识。
\paragraph{product}
商品。
\paragraph{product\_description}
商品描述。将其单独抽出product表的原因是其长度等要素不均一，为业务执行速度以及将来业务扩大考虑，将其单独抽出做表。
\paragraph{product\_keyName}
商品属性标签。商品具体需要什么属性应当随业务的拓展可以自由添加、删除。
\paragraph{product\_keyValue}
商品属性标签值。即商品属性标签与商品本身的笛卡尔积映射。该映射为惰性映射，即旧有商品不会自动添加新添加的商品属性标签对应的值。
\paragraph{product}
商品描述。
\paragraph{product\_tagName}
商品检索标签。可以作为商品分类的依据。
\paragraph{product\_tagMap}
商品检索标签映射。
\paragraph{visitor}
网站访问者。在本项目当中，专指电子商务平台商户。
\paragraph{visitor\_keyName}
网站访问者属性标签。网站访问者具体需要什么属性应当随业务的拓展可以自由添加、删除。
\paragraph{visitor\_keyValue}
网站访问者属性标签值。即网站访问者属性标签与网站访问者本身的笛卡尔积映射。
\subsection{应用服务器层}
使用Struts2框架进行开发。
\paragraph{com.DAO}
提供了Hibernate4对数据库的操作类定义。
\paragraph{com.Entity}
结合业务逻辑进行了对com.DAO的操作模式设计。
\paragraph{com.logistic}负责与表现层进行交互，并进一步细化业务逻辑。
\paragraph{com.Tool}一些工具类。
\subsection{表现层}
本层全部不使用jsp，主要是考虑快速迭代开发。作为替代，在html页面中插入大量javascript通过Ajax进行与服务器的数据交互。本处根路径是应用WebContent。
\paragraph{数据格式}
服务器发回数据使用JSON格式，向服务器提交数据均采用POST请求。其中，密码采用SHA1加密，加密函数在js/sha1.js当中。
\paragraph{Ajax}
使用js/prototype.js进行Ajax处理。具体业务逻辑实现在各个页面当中。
\paragraph{其他}
使用了淘宝样式的imgSlider。在js/imgSlider.js中。
\section{模块介绍}\footnote{本处根路径是src文件夹。另外，部分模块将不予介绍，因为其功能极其简单或者不建议本文档阅读者进行修改。}
\subsection{com.DAO}\footnote{详情以hibernate.cfg.xml为准。}
该模块实现将数据对象化，并没有添加过多的业务逻辑。
\subsection{com.Entity}
这里是数据持久层与业务逻辑层的交界处。
\paragraph{com.Entity}
\subparagraph{Basic}
作为本包下类的夫类存在。
\subsection{com.Entity.Product}
\paragraph{com.Entity.Product.ProductImplement}
本接口规范了对商品的操作，包括：
\subparagraph{public String getValue(String key)}
获取商品属性标签值。
\subparagraph{public void altValue(String key,String value()}
修改商品属性标签值。
\subparagraph{public void addKey(String key,String value)}
为商品属性添加标签。
\subparagraph{public Map<String,String>iterator()}
枚举商品属性标签。
\subparagraph{public Product\_descriptionImplement getDescription()}
获取商品描述。
\subparagraph{public void setDescription(Product\_descriptionImplement description()}
修改商品描述。
\subparagraph{public void save()}
保存商品修改或添加商品到数据库。
\subparagraph{public boolean map()}
映射商品属性，及将数据库商品属性读取到本接口实例对象。
\subparagraph{public void setProductId(String productId)}
修改商品Id为productId。
\subparagraph{public String getProductId()}
获取商品Id。
\subparagraph{public void delete()}
删除商品。

\paragraph{com.Entity.Product.Product\_descriptionImplement}
商品描述接口。
\subparagraph{public String toString()}
转化为字符串。
\subparagraph{public void save()}
保存商品描述更改。
\subparagraph{public String getDescription()}
获取商品描述。
\subparagraph{public void setDescription(String description)}
修改商品描述为description。
\subparagraph{public String getDescriptionId()}
获取商品描述Id。
\subparagraph{public void setDescriptionId(String descriptionId)}
修改商品描述Id为descriptionId。

\paragraph{com.Entity.Product.Product\_tagImplement}
商品检索标签接口。
\subparagraph{public List<String> getProductId()}
获取被检索标签标注的商品的Id。
\subparagraph{public void connectWithProduct(ProductImplement product)}	
将检索标签施加与商品product。
\subparagraph{public String getProduct\_tagNameId()}
获取标签名称Id。
\subparagraph{public String getProduct\_tagName()}
获取标签名称。

\paragraph{com.Entity.Product.Product extends ProductImplement}商品接口的实现\footnote{对于接口的实现，接口中对应的方法如无特殊情况都将不再详细说明}。
\subparagraph{public Product()}
返回一个商品，需要初始化其内容后方可使用其方法。
\subparagraph{public Product(String productId)}
通过productId加载商品。
\subparagraph{public Product(Product\_descriptionImplement description)}
一般用来生成新商品——根据商品描述建立商品。就是说：如果要在数据库当中加入新的商品，必须先加入新的商品描述才能建立新商品。
\subparagraph{public static List iteratorProducts(int max, int first,String productOwnerId)}
获取商户名下商品列表。其中max和first分别指定分页的页面大小与页面第一条记录。productOwnerId告知商户Id。
\subparagraph{public static Integer countProducts(String productOwnerId)}
获取商户名下商品总数。productOwnerId告知商户Id。
\subparagraph{public void save()}
详情见接口。
\subparagraph{public void saveKeyValue(String keyNameId, String[] target)}
详情见接口。
\subparagraph{public boolean map()}
详情见接口。
\subparagraph{public void altValue(String key, String value)}
详情见接口。
\subparagraph{public void addKey(String key, String value)}
详情见接口。
\subparagraph{public String getValue(String key)}
详情见接口。
\subparagraph{public String[] getValueArray(String key)}
\subparagraph{public String getProductId()}
详情见接口。
\subparagraph{public void setProductId(String productId)}
详情见接口。
\subparagraph{public Product\_descriptionImplement getDescription()}
详情见接口。
\subparagraph{public void setDescription(Product\_descriptionImplement description)}
详情见接口。
\subparagraph{public Map<String, String[]> getKeyValueMap()}
详情见接口。
\subparagraph{public void setKeyValueMap(Map<String, String[]> keyValueMap)}
详情见接口。
\subparagraph{public Map<String, String> iterator()}
获取商品全部属性标签。
\subparagraph{public void delete()}
该实现删除表product和表product\_keyValue中内容。后者删除有关商品标签“owner”的信息。

\paragraph{com.Entity.Product.Product\_description extends Product\_descriptionImplement}商品描述实现。
\subparagraph{public Description()}
返回一个商品描述，需要初始化其内容后方可使用其方法。
\subparagraph{public Description(String description)}
使用description描述创建一个新商品描述以插入数据库。
\subparagraph{public static Product\_descriptionImplement load(String descriptionId)}
根据descriptionId载入商品描述
\subparagraph{public String getDescriptionId()}
详情见接口。
\subparagraph{public void setDescriptionId(String descriptionId)}
详情见接口。
\subparagraph{public String toString()}
详情见接口。
\subparagraph{public String getDescription()}
详情见接口。
\subparagraph{public void setDescription(String description)}
详情见接口。

\paragraph{com.Entity.Product.Product\_tag extends Product\_tagImplement}商品检索标签实现。
\subparagraph{public static List iteratorTags(String max, String first)}
返回list供枚举检索标签，通过max、first控制分页。返回结果已经按照检索标签被使用次数降序排列。
\subparagraph{public static List loadProduct(ProductImplement product)}
返回某商品product的检索标签链表。
\subparagraph{public static Product\_tag loadByProduct\_tagName(String product\_tagName)}
根据检索标签名字product\_name生成检索标签对象。
\subparagraph{public Product\_tag(String product\_tagNameId)}
根据product\_tagNameId载入检索标签。
\subparagraph{public void connectWithProduct(ProductImplement product)}
详情见接口。
\subparagraph{public static boolean product\_tagNameIsExist(String product\_tagName)}
检测某标签是否存在于数据库。
\subparagraph{public List getProducts()}
详情见接口。
\subparagraph{public List getProductId()}
详情见接口。
\subparagraph{public String getProduct\_tagNameId()}
详情见接口。
\subparagraph{public void setProduct\_tagNameId(String product\_tagNameId)}
详情见接口。
\subparagraph{public String getProduct\_tagName()}
详情见接口。
\subparagraph{public void setProduct\_tagName(String product\_tagName)}
详情见接口。

\subsection{com.Entity.Visitor}
\paragraph{com.Entity.Visitor.VisitorImplement}
本接口规范了一系列对平台访问者Visitor的操作方法。
\subparagraph{public String getPwd()}
获取访问者密码。
\subparagraph{public void setPwd(String password)}
修改访问者密码为password。
\subparagraph{public String getVisitorName()}
获取访问者用户名。
\subparagraph{public String getVisitorId()}
获取访问者Id。
\subparagraph{public String getValue(String key)}
获取访问者属性标签key的值。
\subparagraph{public void altValue(String key,String value)}
修改访问者属性标签key的值。
\subparagraph{public void addKey(String key,String value)}
添加访问者属性标签key的值。
\subparagraph{public Map<String,String>iterator()}
枚举访问者属性。
\subparagraph{public boolean hasPrivilege(ProductImplement product)}
检查访问者是否对某商品具有权限。
\subparagraph{public boolean map()}
映射访问者属性标签到对象。
\subparagraph{public void save()}
保存访问者更改。
\subparagraph{public String isExist(String visitorName,String password)}
检测访问者是否存在于数据库中。
\subparagraph{public boolean isExist()}
检测当前访问者对象是否可用。

\paragraph{com.Entity.Visitor.Visitor extends VisitorImplement}
是接口的实现。
\subparagraph{public static Visitor newVisitor(String visitorName, String password)}
创建新访问者，即注册。
\subparagraph{public static Visitor loadVisitor(String visitorId)}
根据visitorId载入访问者。
\subparagraph{public Visitor(String visitorName, String password)}
根据visitorName和password载入访问者，即登录。
\subparagraph{public boolean isExist()}
详情见接口。
\subparagraph{public String isExist(String visitorName, String password)}
详情见接口。
\subparagraph{public String getPwd()}
详情见接口。
\subparagraph{public void setPwd(String password)}
详情见接口。
\subparagraph{public String getValue(String key)}
详情见接口。
\subparagraph{public String[] getValueArray(String key)}
详情见接口。
\subparagraph{public void altValue(String key, String value)}
详情见接口。
\subparagraph{public void addKey(String key, String value)}
详情见接口。
\subparagraph{public Map<String, String> iterator()}
详情见接口。
\subparagraph{public boolean hasPrivilege(ProductImplement product)}
详情见接口。
\subparagraph{public boolean map()}
详情见接口。
\subparagraph{public void save()}
详情见接口。
\subparagraph{public void saveKeyValue(String[] target)}
保存用户的某个属性标签。
\subparagraph{public String getVisitorId()}
详情见接口。
\subparagraph{public void setVisitorId(String visitorId)}
详情见接口。
\subparagraph{public String getVisitorName()}
详情见接口。
\subparagraph{public void setVisitorName(String visitorName)}
详情见接口。

\subsection{com.logistic}
本模块处理业务逻辑并与前台页面进行交互。
\paragraph{Basic extends ActionSupport implements ServletRequestAware}
包下所有类的父类。
\subparagraph{public boolean isOnline()}
察看用户当前是否在线。
\subparagraph{public void addVisitorToSession(String visitorName,String password)}
将访问者信息写入session。
\subparagraph{public void addSessionToVisitor()}
访问者信息从session中读出。
\subparagraph{abstract public Map<String,String> getResult()}
JSON返回方法。要求每个子类必须实现。
\subparagraph{public void setResult(Map<String, String> result)}
修改JSON返回Map。
\subparagraph{public void setServletRequest(HttpServletRequest request)}
实现接口方法。输入相当于Servlet当中的request到对象中。

\paragraph{com.logistic.FileManager extends Basic implements ServletResponseAware}
文件上传、下载管理类。
\subparagraph{public String upload()}
文件上传，专门针对CKEditor实现，返回图片的读取路径。
\subparagraph{public String addOneProductImage()}
为商品添加一张图片。这里的图片指的是展示图，而不是在商品描述当中的图。
\subparagraph{public String download()}
文件下载。
\subparagraph{public String getSavePath()}
获得文件存储路径。
\subparagraph{public void addSessionToVisitor()}
详情见接口。
\subparagraph{public Map<String, String> getResult()}
详情见接口。
\subparagraph{public void setServletResponse(HttpServletResponse response)}
详情见接口。
\subparagraph{public void setSavePath(String savePath)}
将配置文件中配置的文件存储路径传如对象。
\subparagraph{public File getUpload()}
获取上传的文件。
\subparagraph{public void setUpload(File upload)}
将访问者传输的文件传入对象。
\subparagraph{public String getUploadFileName()}
获取上传文件的名字。
\subparagraph{public void setUploadFileName(String uploadFileName)}
将上传文件的名字从浏览器传入服务器对象。
\subparagraph{public String getUploadContentType()}
获取上传文件类型。
\subparagraph{public void setUploadContentType(String uploadContentType)}
将上传文件的类型传入服务器对象。
\subparagraph{public String getBaseUrl()}
获取上传文件的互联网访问根路径。
\subparagraph{public void setBaseUrl(String baseUrl)}
从配置文件读取上传文件的互联网访问根路径。
\subparagraph{public InputStream getInputStream()}
获取向浏览器写数据的流。
\subparagraph{public void setInputStream(InputStream inputStream)}
从服务器获取写数据流。该流类似从Servlet中的response获取的流。
\subparagraph{public InputStream getImage()}
获取写图片流。
\subparagraph{public String[] getProductId()}
获取商品Id。主要是为了明确上传文件或图片是从属于哪个商品。
\subparagraph{public void setProductId(String[] productId)}
从浏览器获取的商品Id写入对象。

\paragraph{com.logistics.ProductOwner extends Basic}
执行对商品的数据库非读操作。
\subparagraph{public String applyTagsToProduct()}
关联检索标签与商品。
\subparagraph{public String iteratorProducts()}
枚举商品的属性。
\subparagraph{public String altProduct()}
修改商品属性信息。
\subparagraph{public String clearProduct()}\footnote{未调试、使用。}
清空商品数量。
\subparagraph{public String deleteProduct()}
删除商品。
\subparagraph{public String addProduct()}
添加商品。
\subparagraph{public String[] getVisitorName()}
获取访问者名字。
\subparagraph{public void setVisitorName(String[] visitorName)}
从浏览器传入对象访问者名字。
\subparagraph{public String[] getPassword()}
获取访问者密码。
\subparagraph{public void setPassword(String[] password)}
从浏览器传入对象访问者密码。
\subparagraph{public String[] getProductId()}
获取商品Id。
\subparagraph{public void setProductId(String[] productId)}
从浏览器传入对象商品密码。
\subparagraph{public String[] getProduct\_keyName()}
获取商品属性标签名称。
\subparagraph{public void setProduct\_keyName(String[] product\_keyName)}
从浏览器传入对象商品属性标签名称。
\subparagraph{public String[] getProduct\_keyValue()}
获取商品属性值。
\subparagraph{public void setProduct\_keyValue(String[] product\_keyValue)}
从浏览器传入对象商品属性值。
\subparagraph{public String[] getProductDescription()}
获取商品描述。
\subparagraph{public void setProductDescription(String[] productDescription)}
从浏览器传入对象商品描述。
\subparagraph{public void setVisitor(String visitorName,String password)}
修改访问者。
\subparagraph{public Map<String, String> getResult()}
详情见接口。
\subparagraph{public String[] getMax()}
获取分页信息：每页容量。
\subparagraph{public void setMax(String[] max)}
从浏览器传入分页信息：每页容量。
\subparagraph{public String[] getFirst()}
获取分页信息：当前页面第一条在数据库当中的排序。
\subparagraph{public void setFirst(String[] first)}
从浏览器传入分页信息：当前页面第一条在数据库当中的排序。
\subparagraph{public String[] getProduct\_tagName()}
获取商品检索标签名字。
\subparagraph{public void setProduct\_tagName(String[] product\_tagName)}
从浏览器传入对象商品检索标签名字。

\paragraph{com.logistic.Visitor extends Basic}
普通访问权限操作类。
\subparagraph{public String viewOneTag()}
检索含有某检索标签的商品。\footnote{未测试。}
\subparagraph{public String viewOneProductTags()}
察看某商品的检索标签。
\subparagraph{public String iteratorTags()}
枚举检索标签。结果默认按照标签使用量排序。
\subparagraph{public String[] getMax()}
获取分页信息。
\subparagraph{public void setMax(String[] max)}
传入分页信息。
\subparagraph{public String[] getFirst()}
获取分页信息。
\subparagraph{public void setFirst(String[] first)}
传入分页信息。
\subparagraph{public String login()}
登录。
\subparagraph{public String viewProductOutline()}
察看商品简要说明，即不包涵商品描述。
\subparagraph{public String viewOneProduct()}
察看某商品详细信息。
\subparagraph{public String[] getVisitorName()}
获取访问者用户名。
\subparagraph{public void setVisitorName(String[] visitorName)}
传入访问者用户名。
\subparagraph{public String[] getPassword()}
获取访问者密码。
\subparagraph{public void setPassword(String[] password)}
传入访问者密码。
\subparagraph{public String[] getProductId()}
获取商品Id。
\subparagraph{public void setProductId(String[] productId)}
传入商品Id。
\subparagraph{public Map<String, String> getResult()}
详情见接口。
\subparagraph{public String[] getProduct\_tagNameId()}
获取商品检索标签名称Id。
\subparagraph{public void setProduct\_tagNameId(String[] product\_tagNameId)}
传入商品检索标签名称Id。
\subsection{com.listener}
监听服务器信息。
\paragraph{com.listener.OnlineListener implements HttpSessionListener}
监听Session的创建与销毁，并进行统计。
\paragraph{com.listener.Starter}
服务启动即设置变量以保存当前活跃Session数量。
\paragraph{com.listener.Statistician}
获取当前Session活跃数量的类。
\subparagraph{public String onlineStastic()}
监听当前Session活跃数量。

\subsection{com.Tool}
一些工具类。
\paragraph{com.Tool.DatabaseControler}
数据库控制类。
\paragraph{com.Tool.RandomStringCreater}
随机字符串生成器。

\section{展望}
\subsection{拓展性}
本平台提供了较高的拓展性供二次开发。比如商品属性标签，只需要在数据库添加相应标签名称，在页面增加相应标签赋值模块即可。请使用者自行参考product\_keyName表以及相关操作。
\subsection{检索}
以Xunsearch搜索引擎为例，只需要导入product下各个表，简单设置即可。详情请参考Xunsearch搜索引擎文档。

\section{结语}
由于时间限制，很多功能没有做出来。比如订单、运单系统。本次设计的精髓在于尽可能分表——这反应到业务逻辑上就是尽可能细化每个步骤——这当然是在尽可能按时交付项目的情况下。\footnote{最后吐槽一句：架构我做，编码我做，测试我做，页面我做，文档我做——注孤生的节奏啊……}
\end{document}
